package com.paw.ruoyi.admin.service.impl;

import java.io.IOException;
import java.io.InputStream;

import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSON;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.aliyun.oss.model.StorageClass;
import com.paw.ruoyi.admin.common.domain.Result;
import com.paw.ruoyi.admin.config.AliyunOssProperty;
import com.paw.ruoyi.admin.exceptions.file.FileNameLengthLimitExceededException;
import com.paw.ruoyi.admin.exceptions.file.InvalidExtensionException;
import com.paw.ruoyi.admin.service.IFileUploadService;
import com.paw.ruoyi.admin.utils.file.FileUploadUtils;
import com.paw.ruoyi.admin.utils.file.MimeTypeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile;

/**
 * @author Rubble
 * @date 2022/3/11
 * doc：
 * https://help.aliyun.com/document_detail/84781.html
 **/


@Slf4j
public class AliyunOssService implements IFileUploadService {

  @Autowired
  private AliyunOssProperty ossProperty;


  @Override
  public Result<String> getDomainUrl () {
    String domainUrl =ossProperty.getBucketUrl();
    return Result.result(domainUrl);
  }

  @Override
  public Result<String>  getUrl (String key) {
    String url = ossProperty.getBucketUrl()+key;
    return Result.result(url);
  }

  @Override
  public Result<String>  getKey (String url) {
    String key = url.replace(ossProperty.getBucketUrl(),"");
    return Result.result(key);
  }

  @Override
  public Result<String> uploadFile (MultipartFile file) throws InvalidExtensionException, IOException {

    int fileNameLength = file.getOriginalFilename().length();
    if (fileNameLength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
      throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
    }

    FileUploadUtils.assertAllowed(file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);

    String objectName  = ossProperty.getUploadPath() + FileUploadUtils.extractFilename(file);

    return ossUpload(file.getInputStream(),objectName);

  }

  @Override
  public Result<String> upload (InputStream inputStream,String fileName) {

    String ext = FileUtil.extName(fileName);
    FileUploadUtils.isAllowedExtension(ext, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
    String objectName  = ossProperty.getUploadPath() + FileUploadUtils.extractFilename(fileName);
    return ossUpload(inputStream,objectName);
  }


  private Result<String> ossUpload(InputStream inputStream,String objectName){
    // 创建OSSClient实例。
    OSS ossClient = new OSSClientBuilder().build(ossProperty.getEndpoint(),  ossProperty.getAccessKeyId(), ossProperty.getAccessKeySecret());
    try {
      // 创建PutObjectRequest对象。
      PutObjectRequest putObjectRequest = new PutObjectRequest(ossProperty.getBucketName(), objectName, inputStream);
      ObjectMetadata metadata = new ObjectMetadata();
      metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
      metadata.setObjectAcl(CannedAccessControlList.PublicRead);
      String ext = FileUtil.extName(objectName);
      if(FileUploadUtils.isAllowedExtension(ext,MimeTypeUtils.IMAGE_EXTENSION)){
        metadata.setContentType(FileUploadUtils.getOSSContentType(ext));
      }
      putObjectRequest.setMetadata(metadata);
      // 上传文件。
      PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);
      log.info("oss上传文件 putObjectResult {}", JSON.toJSONString(putObjectResult));

      String resultUrl = ossProperty.getBucketUrl()+"/"+objectName;
      return Result.result(resultUrl);
    } catch (OSSException oe) {
      log.error("oss 上传文件异常. Error Message: {} Error Code: {}", oe.getErrorMessage(), oe.getErrorCode(), oe);
    } catch (ClientException ce) {
      log.error("oss上传文件异常. {}",ce.getMessage(), ce);
    } finally {
      if (ossClient != null) {
        ossClient.shutdown();
      }
    }

    return Result.error("上传文件失败");
  }

}
